/*
######################################################################
# #
# Matrix86 Cylinder Texture Sample #
# #
# Copyright (C) 2008 Matrix86 #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# as published by the Free Software Foundation; either version 2 #
# of the License, or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# http://www.gnu.org/copyleft/gpl.html #
# #
# Linux: gcc -o textureSample textureSample.cpp -lGL -lglut #
######################################################################
*/
#include <iostream>
#include <GL/glut.h>
/* ascii codes for various special keys */
#define ESCAPE 27
#define PAGE_UP 73
#define PAGE_DOWN 81
#define UP_ARROW 72
#define DOWN_ARROW 80
#define LEFT_ARROW 75
#define RIGHT_ARROW 77
GLint FPS = 30; // Frame per Secondo. Vengono usati nella funzione di animazione
// per controllare il massimo numero di frame al secondo dell'animazione
GLfloat xrot=0; // x rotation
GLfloat yrot=0; // y rotation
GLfloat xspeed=0; // x rotation speed
GLfloat yspeed=0; // y rotation speed
GLuint texture[3];
GLuint filter;
GLfloat z=-5.0f;
int spin_x = 0, old_x = 0; // spin_ indica di quanto si deve ruotare la scena
int spin_y = 0, old_y = 0; // old_ indica la vecchia posizione del cursore
int fase = 0,old_fase=0; // specifica lo stato dell' animazione
/* Struttura per l'immagine - contiene altezza, larghezza, e dati */
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
/*
* processa l'azione selezionata dal menu
*
* op - intero che rappresenta l'azione selezionata nel menu
*/
void menu(int op) {
switch(op) {
case 'Q':
case 'q':
exit(0);
}
}
/*
* invocata da GLUT quando un tasto viene premuto
*
* key - tasto premuto
* x, y - coordinate del cursore del mouse
*/
void keyboardDown(unsigned char key, int x, int y) {
switch(key) {
case 'Q':
case 'q':
case 27: // ESC
exit(0);
break;
case 'a':
break;
}
}
void specialKeyPressed(int key, int x, int y)
{
usleep(100);
switch (key) {
case GLUT_KEY_PAGE_UP:
z-=0.02f;
break;
case GLUT_KEY_PAGE_DOWN:
z+=0.02f;
break;
case GLUT_KEY_UP:
xspeed-=0.01f;
break;
case GLUT_KEY_DOWN:
xspeed+=0.01f;
break;
case GLUT_KEY_LEFT:
yspeed-=0.01f;
break;
case GLUT_KEY_RIGHT:
yspeed+=0.01f;
break;
default:
break;
}
}
/*
* invocata da GLUT quando un tasto viene rilasciato
*
* key - tasto premuto
* x, y - coordinate del cursore del mouse
*/
void keyboardUp(unsigned char key, int x, int y) {}
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // Grandezza immagine in bytes
unsigned long i;
unsigned short int planes; // Numero piani nell'immagine
unsigned short int bpp; // Numero bits per pixel
char temp;
if ((file = fopen(filename, "rb"))==NULL)
{
printf("File Not Found : %s\n",filename
);
return 0;
}
fseek(file, 18, SEEK_CUR);
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename
);
return 0;
}
printf("Width of %s: %lu\n", filename, image->sizeX
);
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename
);
return 0;
}
printf("Height of %s: %lu\n", filename, image->sizeY
);
// Calcola la grandezza (assumendo 24 bits o 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename
);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes
);
return 0;
}
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename
);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp
);
return 0;
}
fseek(file, 24, SEEK_CUR);
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename
);
return 0;
}
for (i=0;i<size;i+=3) {
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
return 1;
}
// Load Bitmaps And Convert To Textures
GLvoid LoadGLTextures(GLvoid) {
// Load Texture
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad("img1.bmp", image1)) {
exit(1);
}
// Create Textures
glGenTextures(3, &texture[0]);
// texture 1 (poor quality scaling)
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // cheap scaling when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // cheap scaling when image smalled than texture
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
// texture 2 (linear scaling)
glBindTexture(GL_TEXTURE_2D, texture[1]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
// texture 3 (mipmapped scaling)
glBindTexture(GL_TEXTURE_2D, texture[2]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); // scale linearly + mipmap when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
// 2d texture, 3 colors, width, height, RGB in that order, byte data, and the data.
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
};
/*
* invocata quando la finestra cambia dimensione, oppure รจ occlusa da un'altra finestra
*
* width. height - dimensioni attuali della finestra
*/
void reshape(int width, int height)
{
GLfloat fieldOfView = 45.0f;
glViewport (0, 0, (GLsizei) width, (GLsizei) height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(fieldOfView, (GLfloat) width/(GLfloat) height, 0.1, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/*
* disegna gli assi
*
* lenght - lunghezza degli assi
*/
void DrawAxes(float length)
{
glPushMatrix();
glScalef(length, length, length);
glLineWidth(2.f);
glBegin(GL_LINES);
// x red
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.f, 0.f, 0.f);
glVertex3f(1.f, 0.f, 0.f);
// y green
glColor3f(0.f, 1.f, 0.f);
glVertex3f(0.f, 0.f, 0.f);
glVertex3f(0.f, 1.f, 0.f);
// z blue
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, 0.f, 0.f);
glVertex3f(0.f, 0.f, 1.f);
glEnd();
glLineWidth(1.f);
glPopMatrix();
}
void DisegnaCilindro(float raggio,float altezza){
glPushMatrix();
GLUquadricObj *quadObj;
quadObj = gluNewQuadric();
//gluQuadricDrawStyle(quadObj, GLU_FILL);
gluQuadricTexture(quadObj, GL_TRUE); // Cilindro texturizzato
gluQuadricNormals(quadObj, GLU_SMOOTH);
glRotatef(90,1,0,0);
glTranslatef(0,0,-0.5);
gluCylinder(quadObj, raggio, raggio, altezza, 20, 20);
glPopMatrix();
}
/*
* disegna la scena
*/
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,z); // move z units out from the screen.
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
glBindTexture(GL_TEXTURE_2D, texture[filter]); // choose the texture to use.
//glBegin(GL_QUADS); // begin drawing a cube
DisegnaCilindro(1,3);
// Front Face (note that the texture's corners have to match the quad's corners)
glNormal3f( 0.0f, 0.0f, 1.0f); // front face points out of the screen on z.
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
glEnd(); // done with the polygon.
xrot+=xspeed; // X Axis Rotation
yrot+=yspeed; // Y Axis Rotation
// since this is double buffered, swap the buffers to display what just got drawn.
glutSwapBuffers();
}
/*
* invocata ogni volta che non ci sono eventi pendenti da processare
*/
void idle() { }
/*
* inizializza lo stato di OpenGL
*
* width, height - larghezza e altezza della finestra OpenGL
*/
void initGL(int width, int height)
{
LoadGLTextures(); // load the textures.
glEnable(GL_TEXTURE_2D); // Enable texture mapping.
// colore e tipo delle luci
GLfloat light_ambient_0[] = {0.65, 0.65, 0.65, 1.0};// colore ambiente della luce 0
GLfloat light_diffuse_0[] = {1.0, 1.0, 1.0, 1.0}; // colore diffusione della luce 0
GLfloat light_specular_0[] = {1.0, 1.0, 1.0, 1.0}; // colore speculare della luce 0
GLfloat light_position_0[] = {5.0, 5.0, 0.0, 0.0}; // posizione della luce 0
glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient_0);
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse_0);
glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular_0);
glLightfv (GL_LIGHT0, GL_POSITION, light_position_0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
reshape(width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
int main(int argc, char** argv)
{
int width = 800;
int eight = 600;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(width, eight);
glutInitWindowPosition(100, 100);
glutCreateWindow("Cylinder Texture Example Matrix86");
// registra le callback
glutKeyboardFunc(keyboardDown);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(&specialKeyPressed);
glutReshapeFunc(reshape);
glutDisplayFunc(draw);
glutIdleFunc(draw);
//glutTimerFunc((int) 1000/FPS, animation, 0);
glutIgnoreKeyRepeat(false); // process keys held down
// crea il menu principale (apribile con click destro)
glutCreateMenu(menu);
//glutAddMenuEntry("Start/Stop", 'a');
glutAddMenuEntry("Quit", 'q');
glutAttachMenu(GLUT_RIGHT_BUTTON);
// inizializza lo stato di OpenGL
initGL(width, eight);
// entra nel rendering loop
glutMainLoop();
return 0;
}